package middlewares

import (
	"bluebell/controller"
	"bluebell/dao/mysql"
	"bluebell/models"
	"bluebell/pkg/jwt"
	"go.uber.org/zap"
	"strings"

	"github.com/gin-gonic/gin"
)

// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
	return func(c *gin.Context) {
		// 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
		// 这里假设Token放在Header的Authorization中，并使用Bearer开头
		// Authorization: Bearer xxxxxxx.xxx.xxx  / X-TOKEN: xxx.xxx.xx
		// 这里的具体实现方式要依据你的实际业务情况决定
		authHeader := c.Request.Header.Get("Authorization")
		if authHeader == "" {
			controller.ResponseError(c, models.CodeNeedLogin)
			c.Abort()
			return
		}
		// 按空格分割
		parts := strings.SplitN(authHeader, " ", 2)
		if !(len(parts) == 2 && parts[0] == "Bearer") {
			controller.ResponseError(c, models.CodeInvalidToken)
			c.Abort()
			return
		}
		// parts[1]是获取到的tokenString，我们使用之前定义好的解析JWT的函数来解析它
		mc, err := jwt.ParseToken(parts[1])
		//fmt.Println(mc)
		if err != nil {
			controller.ResponseError(c, models.CodeInvalidToken)
			c.Abort()
			return
		}
		// 将当前请求的userID信息保存到请求的上下文c上
		c.Set(controller.CtxUserIDKey, mc.UserID)

		c.Next() // 后续的处理请求的函数中 可以用过c.Get(CtxUserIDKey) 来获取当前请求的用户信息
	}
}

// JWTAuthOptionalMiddleware 可选认证中间件（不中断请求）
func JWTAuthOptionalMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 尝试获取Token
		authHeader := c.Request.Header.Get("Authorization")
		if authHeader == "" {
			zap.L().Debug("未提供Token，继续处理请求")
			c.Next()
			return
		}

		// 检查Token格式
		parts := strings.SplitN(authHeader, " ", 2)
		if !(len(parts) == 2 && parts[0] == "Bearer") {
			zap.L().Debug("Token格式错误，继续处理请求")
			c.Next()
			return
		}

		// 解析Token - 不中断请求
		mc, err := jwt.ParseToken(parts[1])
		if err != nil {
			zap.L().Debug("Token解析失败（可选中间件）",
				zap.String("token", parts[1]),
				zap.Error(err))
			c.Next()
			return
		}

		// 检查用户是否存在
		if _, err := mysql.GetUserById(mc.UserID); err == nil {
			// 设置用户ID到上下文
			c.Set(controller.CtxUserIDKey, mc.UserID)
			zap.L().Debug("设置用户ID到上下文（可选中间件）",
				zap.Int64("userID", mc.UserID))
		} else {
			zap.L().Debug("用户不存在（可选中间件）",
				zap.Int64("userID", mc.UserID),
				zap.Error(err))
		}

		c.Next()
	}
}

// AuthManager 管理员中间件身份验证
func AuthManager() func(ctx *gin.Context) {
	return func(c *gin.Context) { // 这里的具体实现方式要依据你的实际业务情况决定
		authHeader := c.Request.Header.Get("Authorization")
		if authHeader == "" {
			controller.ResponseError(c, models.CodeNeedLogin)
			c.Abort()
			return
		}
		// 按空格分割
		parts := strings.SplitN(authHeader, " ", 2)
		if !(len(parts) == 2 && parts[0] == "Bearer") {
			controller.ResponseError(c, models.CodeInvalidToken)
			c.Abort()
			return
		}
		// parts[1]是获取到的tokenString，我们使用之前定义好的解析JWT的函数来解析它
		mc, err := jwt.ParseToken(parts[1])
		if err != nil {
			controller.ResponseError(c, models.CodeInvalidToken)
			c.Abort()
			return
		}
		// 查询用户信息
		id := mc.UserID
		role := mc.Role
		if role != "root" {
			controller.ResponseError(c, models.CodeInvalidToken)
			c.Abort()
			return
		}
		// 数据库查询信息
		if _, err := mysql.GetUserById(id); err != nil {
			controller.ResponseError(c, models.CodeInvalidToken)
			c.Abort()
			return
		}
		// 将当前请求的userID信息保存到请求的上下文c上
		c.Set(controller.CtxUserIDKey, mc.UserID)
		// 后续的处理请求的函数中 可以用过c.Get(CtxUserIDKey) 来获取当前请求的用户信息
		c.Next()
	}
}
